package com.admin.service;

import com.admin.model.SensitiveWords;
import com.admin.model.ServiceInstance;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.shared.Application;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

public class EurekaServiceManagerImpl implements EurekaServiceManager{

    private static final Logger logger = LoggerFactory.getLogger(EurekaServiceManagerImpl.class);

    @Resource
    private EurekaClient eurekaClient;

    private RestTemplate restTemplate = new RestTemplate();

    private ObjectMapper objectMapper = new ObjectMapper();

    @Value("${eureka.service-names}")
    private List<String> defaultServiceNames;

    @Value("${eureka.group-names}")
    private String defaultGroupNames;


    /**
     * 根据服务名称获取所有的服务实例。
     *
     * @return 返回一个包含所有服务实例的列表，如果没有找到服务实例，则返回一个空列表。
     */
    @Override
    public List<ServiceInstance> getServiceInstancesByServiceName() {
        List<ServiceInstance> instances = new ArrayList<>();
        for (String serviceName : defaultServiceNames) {
            Application application = eurekaClient.getApplication(serviceName);
            if (application != null) {
                List<ServiceInstance> serviceInstances = application.getInstances().stream()
                        .map(instance -> new ServiceInstance(instance.getAppName(), instance.getIPAddr(), instance.getPort(), false, instance.getMetadata()))
                        .collect(Collectors.toList());
                instances.addAll(serviceInstances);
            } else {
                logger.info("No instances found for service: {}", serviceName);
            }
        }
        return instances;
    }

    /**
     * 根据“分组”名称获取所有的服务实例。
     *
     * @return 返回一个包含符合指定分组的所有服务实例的列表，如果没有找到服务实例，则返回一个空列表。
     */
    @Override
    public List<ServiceInstance> getServiceInstancesByGroupName() {
        List<ServiceInstance> serviceInstancesByGroup = new ArrayList<>();
        List<Application> applications = eurekaClient.getApplications().getRegisteredApplications();

        for (Application application : applications) {
            for (InstanceInfo instanceInfo : application.getInstances()) {
                String instanceGroup = instanceInfo.getMetadata().get("group");
                if (defaultGroupNames.equals(instanceGroup)) {
                    serviceInstancesByGroup.add(new ServiceInstance(
                            instanceInfo.getAppName(),
                            instanceInfo.getIPAddr(),
                            instanceInfo.getPort(),
                            false,
                            instanceInfo.getMetadata()));
                }
            }
        }

        if (serviceInstancesByGroup.isEmpty()) {
            logger.info("No instances found for group: {}", defaultGroupNames);
        }
        return serviceInstancesByGroup;
    }

    /**
     * 组装服务实例的地址列表。
     *
     * @param serviceInstances 服务实例列表。
     * @return 返回一个包含服务地址的字符串列表，每个地址的格式为“protocol://host:port”。
     */
    @Override
    public List<String> assembleServiceAddresses(List<ServiceInstance> serviceInstances) {
        return serviceInstances.stream()
                .map(serviceInstance -> {
                    String protocol = serviceInstance.isSecure() ? "https://" : "http://";
                    return protocol + serviceInstance.getHost() + ":" + serviceInstance.getPort();
                })
                .collect(Collectors.toList());
    }

    /**
     * 对指定的服务实例执行动作，如发送含有敏感词对象的异步HTTP通知。
     *
     * @param serviceInstances 服务实例列表。
     * @param sensitiveWords 包含敏感词的对象。
     */
    @Override
    public void performActionWithServiceInfo(List<ServiceInstance> serviceInstances, SensitiveWords sensitiveWords) {
        String jsonMessage;
        try {
            // 将 SensitiveWords 对象转换为 JSON 字符串
            jsonMessage = objectMapper.writeValueAsString(sensitiveWords);
        } catch (Exception e) {
            throw new RuntimeException("Error serializing SensitiveWords object", e);
        }

        serviceInstances.forEach(instance -> {
            String serviceAddress = instance.getHost() + ":" + instance.getPort();
            notifyServiceAsync(serviceAddress, jsonMessage);
        });
    }

    /**
     * 异步通知服务实例。
     *
     * @param serviceAddress 服务实例的地址。
     * @param jsonMessage 包含敏感词的JSON消息字符串。
     * @return CompletableFuture<Void>
     */
    @Async
    public CompletableFuture<Void> notifyServiceAsync(String serviceAddress, String jsonMessage) {
        try {
            String url = "http://" + serviceAddress + "/api/notify";
            restTemplate.postForObject(url, jsonMessage, String.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return CompletableFuture.completedFuture(null);
    }
}
